@@ -166,6 +166,8 @@ module Agents |
||
| 166 | 166 |
|
| 167 | 167 |
log "Looking at HIT #{hit_id}. I found #{assignments.length} assignments#{" with the statuses: #{assignments.map(&:status).to_sentence}" if assignments.length > 0}"
|
| 168 | 168 |
if assignments.length == hit.max_assignments && assignments.all? { |assignment| assignment.status == "Submitted" }
|
| 169 |
+ payload = { :answers => assignments.map(&:answers) }
|
|
| 170 |
+ |
|
| 169 | 171 |
if options[:take_majority] == "true" |
| 170 | 172 |
counts = {}
|
| 171 | 173 |
options[:hit][:questions].each do |question| |
@@ -177,14 +179,29 @@ module Agents |
||
| 177 | 179 |
end |
| 178 | 180 |
counts[question[:key]] = question_counts |
| 179 | 181 |
end |
| 182 |
+ payload[:counts] = counts |
|
| 183 |
+ |
|
| 180 | 184 |
majority_answer = counts.inject({}) do |memo, (key, question_counts)|
|
| 181 | 185 |
memo[key] = question_counts.to_a.sort {|a, b| a.last <=> b.last }.last.first
|
| 182 | 186 |
memo |
| 183 | 187 |
end |
| 184 |
- event = create_event :payload => { :answers => assignments.map(&:answers), :counts => counts, :majority_answer => majority_answer }
|
|
| 185 |
- else |
|
| 186 |
- event = create_event :payload => { :answers => assignments.map(&:answers) }
|
|
| 188 |
+ payload[:majority_answer] = majority_answer |
|
| 189 |
+ |
|
| 190 |
+ if all_questions_are_numeric? |
|
| 191 |
+ average_answer = counts.inject({}) do |memo, (key, question_counts)|
|
|
| 192 |
+ sum = divisor = 0 |
|
| 193 |
+ question_counts.to_a.each do |num, count| |
|
| 194 |
+ sum += num.to_s.to_f * count |
|
| 195 |
+ divisor += count |
|
| 196 |
+ end |
|
| 197 |
+ memo[key] = sum / divisor.to_f |
|
| 198 |
+ memo |
|
| 199 |
+ end |
|
| 200 |
+ payload[:average_answer] = average_answer |
|
| 201 |
+ end |
|
| 187 | 202 |
end |
| 203 |
+ |
|
| 204 |
+ event = create_event :payload => payload |
|
| 188 | 205 |
log "Event emitted with answer(s)", :outbound_event => event, :inbound_event => Event.find_by_id(memory[:hits][hit_id.to_sym]) |
| 189 | 206 |
|
| 190 | 207 |
assignments.each(&:approve!) |
@@ -194,6 +211,14 @@ module Agents |
||
| 194 | 211 |
end |
| 195 | 212 |
end |
| 196 | 213 |
|
| 214 |
+ def all_questions_are_numeric? |
|
| 215 |
+ options[:hit][:questions].all? do |question| |
|
| 216 |
+ question[:selections].all? do |selection| |
|
| 217 |
+ selection[:key] == selection[:key].to_f.to_s || selection[:key] == selection[:key].to_i.to_s |
|
| 218 |
+ end |
|
| 219 |
+ end |
|
| 220 |
+ end |
|
| 221 |
+ |
|
| 197 | 222 |
def create_hit(event = nil) |
| 198 | 223 |
payload = event ? event.payload : {}
|
| 199 | 224 |
title = Utils.interpolate_jsonpaths(options[:hit][:title], payload).strip |
@@ -236,6 +236,11 @@ describe Agents::HumanTaskAgent do |
||
| 236 | 236 |
describe "taking majority votes" do |
| 237 | 237 |
before do |
| 238 | 238 |
@checker.options[:take_majority] = "true" |
| 239 |
+ @checker.memory[:hits] = { :"JH3132836336DHG" => @event.id }
|
|
| 240 |
+ mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
|
|
| 241 |
+ end |
|
| 242 |
+ |
|
| 243 |
+ it "should take the majority votes of all questions" do |
|
| 239 | 244 |
@checker.options[:hit][:questions][1] = {
|
| 240 | 245 |
:type => "selection", |
| 241 | 246 |
:key => "age_range", |
@@ -248,11 +253,7 @@ describe Agents::HumanTaskAgent do |
||
| 248 | 253 |
{ :key => ">50", :text => "Over 50 years old" }
|
| 249 | 254 |
] |
| 250 | 255 |
} |
| 251 |
- end |
|
| 252 | 256 |
|
| 253 |
- it "should take the majority votes of all questions" do |
|
| 254 |
- @checker.memory[:hits] = { :"JH3132836336DHG" => @event.id }
|
|
| 255 |
- mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } }
|
|
| 256 | 257 |
assignments = [ |
| 257 | 258 |
FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"sad", "age_range"=>"<50"}),
|
| 258 | 259 |
FakeAssignment.new(:status => "Submitted", :answers => {"sentiment"=>"neutral", "age_range"=>">50"}),
|
@@ -277,6 +278,57 @@ describe Agents::HumanTaskAgent do |
||
| 277 | 278 |
|
| 278 | 279 |
@checker.events.last.payload[:counts].should == { :sentiment => { :happy => 2, :sad => 1, :neutral => 1 }, :age_range => { :">50" => 3, :"<50" => 1 } }
|
| 279 | 280 |
@checker.events.last.payload[:majority_answer].should == { :sentiment => "happy", :age_range => ">50" }
|
| 281 |
+ @checker.events.last.payload.should_not have_key(:average_answer) |
|
| 282 |
+ |
|
| 283 |
+ @checker.memory[:hits].should == {}
|
|
| 284 |
+ end |
|
| 285 |
+ |
|
| 286 |
+ it "should also provide an average answer when all questions are numeric" do |
|
| 287 |
+ @checker.options[:hit][:questions] = [ |
|
| 288 |
+ {
|
|
| 289 |
+ :type => "selection", |
|
| 290 |
+ :key => "rating", |
|
| 291 |
+ :name => "Rating", |
|
| 292 |
+ :required => "true", |
|
| 293 |
+ :question => "Please select a rating:", |
|
| 294 |
+ :selections => |
|
| 295 |
+ [ |
|
| 296 |
+ { :key => "1", :text => "One" },
|
|
| 297 |
+ { :key => "2", :text => "Two" },
|
|
| 298 |
+ { :key => "3", :text => "Three" },
|
|
| 299 |
+ { :key => "4", :text => "Four" },
|
|
| 300 |
+ { :key => "5.1", :text => "Five Point One" }
|
|
| 301 |
+ ] |
|
| 302 |
+ } |
|
| 303 |
+ ] |
|
| 304 |
+ |
|
| 305 |
+ assignments = [ |
|
| 306 |
+ FakeAssignment.new(:status => "Submitted", :answers => { "rating"=>"1" }),
|
|
| 307 |
+ FakeAssignment.new(:status => "Submitted", :answers => { "rating"=>"3" }),
|
|
| 308 |
+ FakeAssignment.new(:status => "Submitted", :answers => { "rating"=>"5.1" }),
|
|
| 309 |
+ FakeAssignment.new(:status => "Submitted", :answers => { "rating"=>"2" }),
|
|
| 310 |
+ FakeAssignment.new(:status => "Submitted", :answers => { "rating"=>"2" })
|
|
| 311 |
+ ] |
|
| 312 |
+ hit = FakeHit.new(:max_assignments => 5, :assignments => assignments) |
|
| 313 |
+ mock(RTurk::Hit).new("JH3132836336DHG") { hit }
|
|
| 314 |
+ |
|
| 315 |
+ lambda {
|
|
| 316 |
+ @checker.send :review_hits |
|
| 317 |
+ }.should change { Event.count }.by(1)
|
|
| 318 |
+ |
|
| 319 |
+ assignments.all? {|a| a.approved == true }.should be_true
|
|
| 320 |
+ |
|
| 321 |
+ @checker.events.last.payload[:answers].should == [ |
|
| 322 |
+ { :rating => "1" },
|
|
| 323 |
+ { :rating => "3" },
|
|
| 324 |
+ { :rating => "5.1" },
|
|
| 325 |
+ { :rating => "2" },
|
|
| 326 |
+ { :rating => "2" }
|
|
| 327 |
+ ] |
|
| 328 |
+ |
|
| 329 |
+ @checker.events.last.payload[:counts].should == { :rating => { :"1" => 1, :"2" => 2, :"3" => 1, :"4" => 0, :"5.1" => 1 } }
|
|
| 330 |
+ @checker.events.last.payload[:majority_answer].should == { :rating => "2" }
|
|
| 331 |
+ @checker.events.last.payload[:average_answer].should == { :rating => (1 + 2 + 2 + 3 + 5.1) / 5.0 }
|
|
| 280 | 332 |
|
| 281 | 333 |
@checker.memory[:hits].should == {}
|
| 282 | 334 |
end |